package com.vin.java.thread.examples;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.Semaphore;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * <br>
 *
 * @author levin
 * @version 1.0.0
 */
public class MultiThreadExamples {
    public static void main(String[] args) throws InterruptedException {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(20, 20,
                0L, TimeUnit.MILLISECONDS,
                new SynchronousQueue<>(), new IncrementNameThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        Semaphore semaphore = new Semaphore(1);
        for (int i = 0; i < 20; i++) {
            threadPoolExecutor.submit(new IncrementRunable(semaphore, i + 1));
        }
        Thread.sleep(10000);
        threadPoolExecutor.shutdownNow();
    }


    static class IncrementNameThreadFactory implements ThreadFactory {
        private final AtomicInteger threadNumber = new AtomicInteger(1);

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(null, r,
                    "increment-thread-" + threadNumber.getAndIncrement(),
                    0);
            return t;
        }
    }

    static class IncrementRunable implements Runnable {

        Semaphore semaphore;
        int acquireCount;

        public IncrementRunable(Semaphore semaphore, int acquireCount) {
            this.semaphore = semaphore;
            this.acquireCount = acquireCount;
        }

        @Override
        public void run() {
            try {
                semaphore.acquire(acquireCount);
                System.out.println(Thread.currentThread().getName() + "---->" + acquireCount);
                semaphore.release(acquireCount + 1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}
